﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading;

namespace EventScavenger
{
    public partial class EventReaperService : ServiceBase
    {
        public EventReaperService()
        {
            InitializeComponent();
            CollectorName = "";
        }

        #region Privates
        private static MainReaperService catalyst = new MainReaperService();
        #endregion

        public string CollectorName { get; set; }

        #region Service events
        protected override void OnStart(string[] args)
        {
            if (CollectorName == "")
                CollectorName = Properties.Settings.Default.CollectorName;

#if DEBUG
            //The following code is simply to ease attaching the debugger to the service to debug the startup routine
            DateTime startTime = DateTime.Now;
            while ((!Debugger.IsAttached) && ((TimeSpan)DateTime.Now.Subtract(startTime)).TotalSeconds < 20)  // Waiting until debugger is attached
            {
                RequestAdditionalTime(1000);  // Prevents the service from timeout
                Thread.Sleep(1000);           // Gives you time to attach the debugger   
            }
            // increase as needed to prevent timeouts
            RequestAdditionalTime(5000);     // for Debugging the OnStart method,     
#endif

            EventLog.WriteEntry("Starting Event Reaper version:" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version
                + "\r\nRunning as Collector: " + CollectorName
                , EventLogEntryType.Information, (int)EventIDCodes.SystemEvents
                );
            Thread.Sleep(1000);

            LogExtendedMessage("Setting unhandled exception handler...", EventLogEntryType.Information);
            AppDomain currentDomain = AppDomain.CurrentDomain;
            currentDomain.UnhandledException += new UnhandledExceptionEventHandler(currentDomain_UnhandledException);
            currentDomain.FirstChanceException += new EventHandler<System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs>(currentDomain_FirstChanceException);

            LogExtendedMessage("Setting catalyst properties", EventLogEntryType.Information);
            catalyst.Log = this.EventLog;
            catalyst.Running = true;
            catalyst.Paused = false;
            catalyst.CollectorName = CollectorName;
            catalyst.SQLCommandTimeout = Properties.Settings.Default.SqlCommandTimeOutSec;
            catalyst.SQLServer = Properties.Settings.Default.SQLServer;
            catalyst.Database = Properties.Settings.Default.Database;
            catalyst.UserName = Properties.Settings.Default.UserName;
            catalyst.Password = Properties.Settings.Default.Password;
            catalyst.TrustServerCertificate = Properties.Settings.Default.TrustServerCertificate;
            LogExtendedMessage("Initializing performance counters", EventLogEntryType.Information);
            catalyst.InitPerformanceCounters(this.EventLog.Source);

            LogExtendedMessage("Kicking off main thread", EventLogEntryType.Information);
            catalyst.Run();
            LogExtendedMessage("Exiting OnStart", EventLogEntryType.Information);
        }
        protected override void OnStop()
        {
            catalyst.Running = false;
            EventLog.WriteEntry("Stopping Event Reaper version:" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version
                + "\r\nRunning as Collector: " + CollectorName
                , EventLogEntryType.Information, (int)EventIDCodes.SystemEvents
                );
        }
        protected override void OnPause()
        {
            LogExtendedMessage("Pausing service " + CollectorName, EventLogEntryType.Information);
            catalyst.Paused = true;
            base.OnPause();
        }
        protected override void OnContinue()
        {
            LogExtendedMessage("Continuing service " + CollectorName, EventLogEntryType.Information);
            catalyst.Paused = false;
            base.OnContinue();
        } 
        #endregion

        #region Exception handling
        private void currentDomain_UnhandledException(object sender,
                              UnhandledExceptionEventArgs e)
        {
            this.EventLog.WriteEntry(string.Format("This service {0} encountered an unhandled exception!\r\n{1}",
                CollectorName, e.ExceptionObject.ToString()), EventLogEntryType.Error);
        }
        private void currentDomain_FirstChanceException(object sender, System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs e)
        {
            if (!e.Exception.Message.Contains("is out of bounds") &&
                !e.Exception.Message.Contains("The event log may be corrupt.") &&
                !e.Exception.ToString().Contains("System.Net.NetworkInformation.Ping.InternalSend") &&
                !e.Exception.Message.Contains("An exception occurred during a Ping request") &&
                !e.Exception.ToString().Contains("System.Data.SqlClient.SqlException (0x80131904)")
                )
            {
                this.EventLog.WriteEntry(string.Format("This service {0} encountered a first chance exception!\r\n{1}",
                    CollectorName, e.Exception.ToString() + "\r\n" + sender.ToString()), EventLogEntryType.Error);
            }
        } 
        #endregion

        #region Logging error message
        private void LogExtendedMessage(string message, EventLogEntryType logType)
        {
            if (Properties.Settings.Default.EnabledExtendedLogging)
            {
                EventLog.WriteEntry("Exiting OnStart", logType);
            }
        } 
        #endregion
    }
}
